package main

import (
	"fmt"
	"math/rand"
	"strings"
	"sync"
	"time"
)

func getMaxTimeoutCount() int {
	return 2
}

// 助手函数
func helper1(ch chan string, chMeeting chan string) {

	// 阅读邮件
	go func() {
		count := 1
		for i := 1; i < 10; i++ {
			fmt.Printf("助手阅读邮件：%v \n", count)
			time.Sleep(time.Second * 1)
			count = count + 1
		}
	}()

	go func() {
		for i := 1; i < 100; i++ {
			//time.Sleep(time.Second * 1)
			chMeeting <- fmt.Sprintf("会议%v", i)
		}
	}()

	go func() {
		time.Sleep(time.Second * 5)
		for i := 1; i < 5; i++ {
			time.Sleep(time.Second * 1)
			chMeeting <- fmt.Sprintf("会议%v", rand.Int())
		}
	}()

	// 从通道中取消息
	timeOutCount := 0
	for {
		select {
		case msg := <-ch:
			if strings.Contains(msg, "通知") {
				fmt.Printf("收到【%v】并阅读\n", msg)
				//ch <- fmt.Sprintf("%v%v", "已经收到" , msg) //返回消息
			}
		case <-time.After(time.Second * 5):
			fmt.Printf("helper1 接收超时：timeOutCount = %v \n", timeOutCount)
			if timeOutCount > getMaxTimeoutCount() {
				fmt.Println("任务完成了")
				return
			}
			timeOutCount++
			//default:
			//	fmt.Println("helper1 接收 default")
		}
	}

}

func If(condition bool, trueVal, falseVal interface{}) interface{} {
	if condition {
		return trueVal
	}
	return falseVal
}

func mainTask(ch chan string, chMeeting chan string, wg sync.WaitGroup) {

	go helper1(ch, chMeeting)

	go func() {
		for i := 1; i < 100; i++ {
			//time.Sleep(time.Second * 1)
			ch <- fmt.Sprintf("通知%v", i)
		}
	}()

	go func() {
		time.Sleep(time.Second * 5)
		for i := 1; i < 5; i++ {
			time.Sleep(time.Second * 1)
			ch <- fmt.Sprintf("通知%v", rand.Int())
		}
	}()

	timeOutCount := 0 //超时次数
	// 从通道中取消息
	for {
		select {
		case msg := <-chMeeting:
			if strings.Contains(msg, "会议") {
				opType := If(rand.Int()%2 == 0, "接受", "拒绝").(string)
				fmt.Printf("%v%v \n", opType, msg)
				//chMeeting <- fmt.Sprintf("%v%v", opType, msg) //返回消息
			}
		case <-time.After(time.Second * 5):
			fmt.Printf("mainTask 接收超时：timeOutCount = %v \n", timeOutCount)
			if timeOutCount > getMaxTimeoutCount() {
				return
			}
			timeOutCount = timeOutCount + 1
			//default:
			//	fmt.Println("mainTask 接收 default")
		}
	}

	fmt.Println("任务完成了")
	wg.Done()
}

func errorLock() {
	c := make(chan int, 10)
	//【主协程中】从一个永远都不可能有值的通道中读取数据，会发生死锁，因为会阻塞主程序的执行
	<-c
}

func main() {
	ch := make(chan string, 10)
	chMeeting := make(chan string, 10)

	wg := sync.WaitGroup{}
	wg.Add(1)
	go mainTask(ch, chMeeting, wg)
	//go errorLock()
	fmt.Println("waiting")
	wg.Wait()
	fmt.Println("wait over")
	close(ch)
	close(chMeeting)
}
